package com.cjkj.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cjkj.common.core.constant.*;
import com.cjkj.common.core.domain.PatVisitIntervalData;
import com.cjkj.common.core.domain.R;
import com.cjkj.common.core.exception.ServiceException;
import com.cjkj.common.core.utils.DateUtils;
import com.cjkj.common.core.utils.StringUtils;
import com.cjkj.common.core.web.domain.AjaxResult;
import com.cjkj.common.core.web.page.TableDataInfo;
import com.cjkj.common.redis.service.RedisService;
import com.cjkj.common.security.utils.SecurityUtils;
import com.cjkj.system.api.RemoteTJ02DataService;
import com.cjkj.system.api.domain.APISmartBraceletData;
import com.cjkj.system.api.domain.SmartBraceletRecords;
import com.cjkj.system.api.domain.request.BraceletHistoryDataReq;
import com.cjkj.system.api.domain.request.BraceletHistoryDataReqEquipmentInfo;
import com.cjkj.system.api.domain.request.EquipmentHistoryReq;
import com.cjkj.system.api.domain.request.RecordsReq;
import com.cjkj.system.api.model.LoginUser;
import com.cjkj.system.domain.TEquipmentUsageRecords;
import com.cjkj.system.domain.THospitalUserSign;
import com.cjkj.system.domain.TPatVisit;
import com.cjkj.system.domain.TWarnSettingHospital;
import com.cjkj.system.domain.dto.HourlyDataReq;
import com.cjkj.system.domain.dto.TJ02ReportsDataReq;
import com.cjkj.system.domain.vo.PatientDetailInfoVo;
import com.cjkj.system.domain.vo.ScreenSignVo;
import com.cjkj.system.domain.vo.WarnSetVo;
import com.cjkj.system.domain.vo.report.*;
import com.cjkj.system.mapper.TEquipmentUsageRecordsMapper;
import com.cjkj.system.mapper.THospitalUserSignMapper;
import com.cjkj.system.mapper.TPatVisitMapper;
import com.cjkj.system.mapper.TWarnSettingHospitalMapper;
import com.cjkj.system.service.ReportTJ02Service;
import com.cjkj.system.util.ReportUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ReportTJ02ServiceImpl implements ReportTJ02Service {

    @Resource
    private TPatVisitMapper patVisitMapper;

    @Resource
    private TEquipmentUsageRecordsMapper equipmentUsageRecordsMapper;

    @Resource
    private RemoteTJ02DataService remoteTJ02DataService;

    @Resource
    private RedisService redisService;

    @Resource
    private THospitalUserSignMapper hospitalUserSignMapper;

    @Resource
    private TWarnSettingHospitalMapper tWarnSettingHospitalMapper;

    @Override
    public HeartRateReportVo getTJ02HeartRateReports(Long visitNo) {
        // 获取患者开单时间和出院时间
        PatVisitIntervalData intervalData = getTimes(visitNo);
        return getBraceletHeartRateReport(visitNo, intervalData.getVisitTime(), intervalData.getOutTime());
    }

    @Override
    public SpO2ReportVo getTJ02SpO2Reports(Long visitNo) {
        // 获取患者开单时间和出院时间
        PatVisitIntervalData intervalData = getTimes(visitNo);
        return getBraceletSpO2Report(visitNo, intervalData.getVisitTime(), intervalData.getOutTime());
    }

    @Override
    public TemperatureReportVo getTJ02TemperatureReports(Long visitNo) {
        // 获取患者开单时间和出院时间
        PatVisitIntervalData intervalData = getTimes(visitNo);
        return getTemperatureReport(visitNo, intervalData.getVisitTime(), intervalData.getOutTime());
    }

    private HeartRateReportVo getBraceletHeartRateReport(Long visitNo, Date visitTime, Date outTime) {
        // 查询监测数据
        List<APISmartBraceletData> apiSmartBraceletDataList = listSmartBraceletData(visitNo, outTime);
        if (apiSmartBraceletDataList.isEmpty()) {
            return null;
        }

        TJ02Report report = getBraceletReport(apiSmartBraceletDataList, ReportConstant.BRACELET_HEART_RATE);
        List<Integer> heartRateAxis = report.getValues();

        HeartRateReportVo heartRateReportVo = new HeartRateReportVo();
        heartRateReportVo.setReportTime(visitTime);
        heartRateReportVo.setAbscissa(report.getTimes());
        heartRateReportVo.setHeartRateAxis(heartRateAxis);
        heartRateReportVo.setHighestHeartRate(heartRateAxis.stream().mapToInt(Integer::intValue).max().orElse(0));
        heartRateReportVo.setLowestHeartRate(heartRateAxis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).min().orElse(0));
        heartRateReportVo.setAvgHeartRate((int) heartRateAxis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).average().orElse(0));

        // 获取预警值
        WarnSetVo warnValue = getWarnValue(visitNo);
        heartRateReportVo.setLowWarnValue(warnValue.getHrLow());
        heartRateReportVo.setHighWarnValue(warnValue.getHrHigh());
        return heartRateReportVo;
    }

    private SpO2ReportVo getBraceletSpO2Report(Long visitNo, Date visitTime, Date outTime) {
        // 查询监测数据
        List<APISmartBraceletData> apiSmartBraceletDataList = listSmartBraceletData(visitNo, outTime);
        if (apiSmartBraceletDataList.isEmpty()) {
            return null;
        }

        TJ02Report spo2Report = getBraceletReport(apiSmartBraceletDataList, ReportConstant.BRACELET_SPO2);
        List<Integer> spO2Axis = spo2Report.getValues();

        SpO2ReportVo spO2ReportVo = new SpO2ReportVo();
        spO2ReportVo.setReportDate(visitTime);
        spO2ReportVo.setAbscissa(spo2Report.getTimes());
        spO2ReportVo.setSpO2Axis(spO2Axis);
        spO2ReportVo.setHighestSpO2(spO2Axis.stream().mapToInt(Integer::intValue).max().orElse(0));
        spO2ReportVo.setLowestSpO2(spO2Axis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).min().orElse(0));
        spO2ReportVo.setAvgSpO2((int) spO2Axis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).average().orElse(0));
        // 轻度(85%~90%)
//        spO2ReportVo.setMildSpO2((int) spO2Axis.stream().filter(e -> e >= 85 && e <= 90).count());
        // 中度(80%~84%)
//        spO2ReportVo.setModerateSpO2((int) spO2Axis.stream().filter(e -> e >= 80 && e <= 84).count());
        // 重度(80%以下)
//        spO2ReportVo.setSevereSpO2((int) spO2Axis.stream().filter(e -> e > 0 && e < 80).count());
        spO2ReportVo.setWarnValue(getWarnValue(visitNo).getSpo2());
        return spO2ReportVo;
    }

    private TemperatureReportVo getTemperatureReport(Long visitNo, Date visitTime, Date outTime) {
        // 查询监测数据
        List<APISmartBraceletData> apiSmartBraceletDataList = listSmartBraceletData(visitNo, outTime);
        if (apiSmartBraceletDataList.isEmpty()) {
            return null;
        }

        TJ02Report report = getBraceletReport(apiSmartBraceletDataList, ReportConstant.BRACELET_TEMPERATURE);
        List<Double> temperatureAxis = new ArrayList<>();
        List<Integer> values = report.getValues();
        values.forEach(e -> {
            temperatureAxis.add((double) e / 10);
        });

        TemperatureReportVo temperatureReportVo = new TemperatureReportVo();
        temperatureReportVo.setReportDate(visitTime);
        temperatureReportVo.setAbscissa(report.getTimes());
        temperatureReportVo.setTemperatureRateAxis(temperatureAxis);
        temperatureReportVo.setHighestTemperatureRate(temperatureAxis.stream().mapToDouble(Double::doubleValue).max().orElse(0));
        temperatureReportVo.setLowestTemperatureRate(temperatureAxis.stream().mapToDouble(Double::doubleValue).min().orElse(0));
        double avg = temperatureAxis.stream().mapToDouble(Double::doubleValue).average().orElse(0);
        DecimalFormat decimalFormat = new DecimalFormat("#.0");
        temperatureReportVo.setAvgTemperatureRate(Double.valueOf(decimalFormat.format(avg)));

        // 获取预警值
        WarnSetVo warnValue = getWarnValue(visitNo);
        temperatureReportVo.setLowWarnValue(warnValue.getTempLow());
        temperatureReportVo.setHighWarnValue(warnValue.getTempHigh());
        return temperatureReportVo;
    }

    private TJ02Report getBraceletReport(List<APISmartBraceletData> apiSmartBraceletDataList, String type){
        // 间隔分钟数
        int intervalMinutes = 30;

        // 1、按时间排序
        List<APISmartBraceletData> timeSortedData = apiSmartBraceletDataList.stream()
                .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                .collect(Collectors.toList());
        // 2、获取第一条数据的时间
        APISmartBraceletData apiSmartBraceletData = timeSortedData.get(0);
        Date start = apiSmartBraceletData.getAcquisitionTime();
        // 获取开始时间、结束时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);
        calendar.set(Calendar.SECOND, 0);
        int minute = calendar.get(Calendar.MINUTE);
        calendar.add(Calendar.MINUTE, intervalMinutes - (minute % intervalMinutes));
        Date end = calendar.getTime();

        List<Integer> values = new ArrayList<>();
        List<Date> abscissa = new ArrayList<>();
        while (!timeSortedData.isEmpty()) {
            // 筛选出对应时间段的数据
            Date finalStart = start, finalEnd = end;
            List<APISmartBraceletData> intervalData = timeSortedData.stream()
                    .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                    .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < finalEnd.getTime())
                    .collect(Collectors.toList());

            start = end;
            Calendar calendar30 = Calendar.getInstance();
            calendar30.setTime(start);
            calendar30.add(Calendar.MINUTE, intervalMinutes);
            end = calendar30.getTime();
            if(intervalData.isEmpty()) {
                continue;
            }

            // 求每十分钟的众数，再进行加权平均
            List<Integer> modeList = getModeList(intervalData, type);
            if(! modeList.isEmpty()) {
                values.add(Integer.parseInt(String.valueOf(ReportUtil.doubleFmt(ReportUtil.getAvg(modeList), 0))));
                abscissa.add(start);
            }
            // 移除
            timeSortedData.removeAll(intervalData);
        }

        TJ02Report report = new TJ02Report();
        report.setTimes(abscissa);
        report.setValues(values);

        return report;
    }

    private List<Integer> getModeList(List<APISmartBraceletData> intervalData, String type){
        List<Integer> mode = new ArrayList<>();
        // 取得第一个时间
        APISmartBraceletData apiSmartBraceletData = intervalData.get(0);
        Date start = apiSmartBraceletData.getAcquisitionTime();
        // 3.2、取每十分钟数据的数据
        for (int j = 0; j < 3; j ++) {
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(start);
            startCal.set(Calendar.SECOND, 0);
            int minute = startCal.get(Calendar.MINUTE);
            // 加十分钟
            startCal.add(Calendar.MINUTE, 10 - (minute % 10));
            Date end = startCal.getTime();

            // 获取十分钟的区间数据
            Date finalStart = start;
            List<APISmartBraceletData> min10Data = new ArrayList<>();
            // 体温需要筛选合法数据
            if(ReportConstant.BRACELET_TEMPERATURE.equals(type)) {
                min10Data = intervalData.stream()
                        .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                        .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < end.getTime()
                                && (StringUtils.isEmpty(e.getPlugStatus()) || SensorConstants.SENSOR_STATUS_LEGAL.equals(e.getPlugStatus())))
                        .collect(Collectors.toList());
            } else {
                min10Data = intervalData.stream()
                        .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                        .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < end.getTime())
                        .collect(Collectors.toList());
            }

            start = end;
            if (min10Data.isEmpty()) {
                continue;
            }

            // 剔除掉脉率、血氧同时为初始值的数据
            List<APISmartBraceletData> excludeInitialValueDatas = min10Data.stream().filter(e -> e.getHeartRate() != EquipmentConstants.INITIAL_HEARTRATE_VALUE && e.getSpo2() != EquipmentConstants.INITIAL_SPO2_VALUE)
                    .collect(Collectors.toList());

            // 获取血氧众数
            if(ReportConstant.BRACELET_SPO2.equals(type)) {
                List<Integer> spo2Data = min10Data.stream()
                        .map(APISmartBraceletData::getSpo2)
                        .filter(e -> e > 0)
                        .collect(Collectors.toList());
                mode.add(spo2Data.isEmpty() ? EquipmentConstants.INITIAL_SPO2_VALUE : (spo2Data.size() == 1 ? spo2Data.get(0) : ReportUtil.getMode(spo2Data)));
            }

            // 脉率众数
            if(ReportConstant.BRACELET_HEART_RATE.equals(type)) {
                List<Integer> heartData = excludeInitialValueDatas.stream()
                        .map(APISmartBraceletData::getHeartRate)
                        .filter(e -> e > 0)
                        .collect(Collectors.toList());
                mode.add(heartData.isEmpty() ? EquipmentConstants.INITIAL_HEARTRATE_VALUE : (heartData.size() == 1 ? heartData.get(0) : ReportUtil.getMode(heartData)));
            }

            // 体温众数
            if(ReportConstant.BRACELET_TEMPERATURE.equals(type)) {
                List<Integer> tempData = min10Data.stream()
                        .map(APISmartBraceletData::getTemperature)
                        .filter(e -> e != null && e > 0 && EquipmentConstants.INITIAL_TEMPERATURE_VALUE != e && EquipmentConstants.INVALID_TEMPERATURE2 != e)
                        .collect(Collectors.toList());
                if(!tempData.isEmpty()) {
                    mode.add(tempData.size() == 1 ? tempData.get(0) : ReportUtil.getMode(tempData));
                }
            }
        }

        return mode;
    }

    /**
     * 多参数监测仪
     * 根据就诊号查询就诊期间的监测数据
     **/
    private List<APISmartBraceletData> listSmartBraceletData(Long visitNo, Date outTime) {

        List<APISmartBraceletData> smartBraceletDataList = new ArrayList<>();

        List<TEquipmentUsageRecords> usageRecordsList = equipmentUsageRecordsMapper.selectAllUseRecordByVisitNo(visitNo);
        for (TEquipmentUsageRecords usageRecord : usageRecordsList) {
            if (usageRecord != null && EquipmentConstants.EQUIPMENT_TYPE_SMART_BRACELET_TYPE.equals(usageRecord.getEquipmentType())) {
                Date startTime = usageRecord.getStartTime();
                Date endTime = usageRecord.getEndTime();
                endTime = (endTime == null || endTime.after(outTime)) ? outTime : endTime;

                //查询设备在该时间段采集的数据
                smartBraceletDataList.addAll(remoteReportSmartBraceletDataList(usageRecord.getEquipmentNo(), startTime, endTime));
            }
        }
        return smartBraceletDataList;
    }

    /**
     * 远程请求多参数监测仪数据
     * @param equipmentNo 设备号
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 监测数据
     */
    private List<APISmartBraceletData> remoteReportSmartBraceletDataList(String equipmentNo, Date startTime, Date endTime) {

        List<APISmartBraceletData> smartBraceletDataList = new ArrayList<>();
        // 组装参数
        RecordsReq recordsReq = new RecordsReq();
        recordsReq.setEquipmentNo(equipmentNo);
        recordsReq.setStartTime(startTime);
        recordsReq.setEndTime(endTime);
        // 远程请求数据
        R<SmartBraceletRecords> smartBraceletRecordsResult = remoteTJ02DataService.listSmartBraceletRecords(recordsReq, SecurityConstants.INNER);
        if (StringUtils.isNotNull(smartBraceletRecordsResult)) {
            if (R.FAIL == smartBraceletRecordsResult.getCode()
                    || StringUtils.isNull(smartBraceletRecordsResult.getData())
                    || StringUtils.isNull(smartBraceletRecordsResult.getData().getDataList())) {
                log.error("查询设备采集数据出错：" + equipmentNo + "," + startTime + "-" + endTime);
                return smartBraceletDataList;
            }

            smartBraceletDataList = smartBraceletRecordsResult.getData().getDataList();
        } else {
            log.error("查询设备采集数据出错：" + equipmentNo + "," + startTime + "-" + endTime);
        }

        return smartBraceletDataList;
    }

    private PatVisitIntervalData getTimes(Long visitNo) {
        // 查询患者信息
        TPatVisit tPatVisit = patVisitMapper.selectTPatVisitByVisitNo(visitNo);
        if (tPatVisit == null) {
            throw new ServiceException("患者信息不存在！");
        }
        // 开单时间
        Date visitTime = tPatVisit.getVisitTime();
        // 疗程天数
        Integer rentalDays = tPatVisit.getRentalDays();
        // 出院时间
        Date outTime  = tPatVisit.getOutTime();
        return DateUtils.getIntervalTime(visitTime, rentalDays, outTime, tPatVisit.getDataType());
    }

    @Override
    public List<TJ02ReportsDataVo> getPatientReportData(TJ02ReportsDataReq req) {
        String visitNos = req.getVisitNos();
        String reportItems = req.getReportItems();
        boolean mergeFlag = req.getMergeFlag() != null && req.getMergeFlag();

        // 需要打印的报告项目
        List<String> reportItemList = Arrays.stream(reportItems.split(",")).collect(Collectors.toList());
        if(!reportItemList.contains(ReportConstant.BRACELET_SPO2) &&
                !reportItemList.contains(ReportConstant.BRACELET_TEMPERATURE) &&
                !reportItemList.contains(ReportConstant.BRACELET_HEART_RATE)) {
            System.err.println("不支持的报告类型：" + reportItems);
            throw new ServiceException("不支持的报告类型！");
        }

        // 获取医生签名
        THospitalUserSign tHospitalUserSign = hospitalUserSignMapper.selectOneByUserId(SecurityUtils.getUserId());
        String sign = tHospitalUserSign == null ? "" : tHospitalUserSign.getSignImg();

        List<TJ02ReportsDataVo> TJ02ReportsDataVoList = new ArrayList<>();
        List<APISmartBraceletData> allData = new ArrayList<>();
        List<PatientDetailInfoVo> allPatInfo = new ArrayList<>();
        // 所有就诊记录
        List<String> visitNoList = Arrays.stream(visitNos.split(",")).collect(Collectors.toList());
        // 获取预警值
        WarnSetVo warnValue = getWarnValue(Long.valueOf(visitNoList.get(0)));
        for (String visitNoStr : visitNoList) {
            // 获取患者开单时间和出院时间
            Long visitNo = Long.valueOf(visitNoStr);
            PatVisitIntervalData intervalData = getTimes(visitNo);
            Date visitTime = intervalData.getVisitTime();
            Date outTime = intervalData.getOutTime();

            // 查询患者信息
            PatientDetailInfoVo detailInfo = patVisitMapper.getDetailInfo(visitNo);
            // 查询监测数据
            List<APISmartBraceletData> apiSmartBraceletDataList = listSmartBraceletData(visitNo, outTime);

            // 是否合并
            if(mergeFlag) {
                // 如果合并，则先将数据汇总
                allData.addAll(apiSmartBraceletDataList);
                allPatInfo.add(detailInfo);
            } else {
                // 如果不合并，则分别计算报告信息
                TJ02ReportsDataVo vo = new TJ02ReportsDataVo();

                PatVisitIntervalData intervalTime = DateUtils.getIntervalTime(detailInfo.getVisitTime(), detailInfo.getRentalDays(), detailInfo.getOutTime(), detailInfo.getDataType());
                detailInfo.setOutTime(intervalTime.getOutTime());
                vo.setPatInfo(detailInfo);

                if(! apiSmartBraceletDataList.isEmpty()) {
                    for (String item : reportItemList) {
                        getReportDataVo(apiSmartBraceletDataList, item, vo, visitTime, warnValue);
                    }

                    // 获取整点护理数据
                    getHourlyNursingData(apiSmartBraceletDataList, reportItemList, visitTime, vo);
                }

                vo.setSignImg(sign);
                TJ02ReportsDataVoList.add(vo);
            }
        }

        if(mergeFlag) {
            TJ02ReportsDataVo vo = new TJ02ReportsDataVo();

            List<PatientDetailInfoVo> patInfos = allPatInfo.stream().sorted(Comparator.comparing(PatientDetailInfoVo::getVisitTime)).collect(Collectors.toList());
            PatientDetailInfoVo patInfo = patInfos.get(0);
            Date visitTime = patInfo.getVisitTime();

            // 患者信息
            PatientDetailInfoVo finalPatInfo = patInfos.get(patInfos.size() - 1);
            Date finalPatVisitTime = finalPatInfo.getVisitTime();
            Integer finalPatRentalDays = finalPatInfo.getRentalDays();

            finalPatInfo.setVisitTime(visitTime);
            finalPatInfo.setRentalDays(patInfos.stream().map(PatientDetailInfoVo::getRentalDays).reduce(Integer::sum).get());
            PatVisitIntervalData intervalTime = DateUtils.getIntervalTime(finalPatVisitTime, finalPatRentalDays, finalPatInfo.getOutTime(), finalPatInfo.getDataType());
            finalPatInfo.setOutTime(intervalTime.getOutTime());

            vo.setPatInfo(finalPatInfo);
            if(! allData.isEmpty()) {
                // 按时间排序
                List<APISmartBraceletData> smartBraceletData = allData.stream().sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime).reversed()).collect(Collectors.toList());
                for (String item : reportItemList) {
                    getReportDataVo(smartBraceletData, item, vo, visitTime, warnValue);
                }
            }

            vo.setSignImg(sign);
            TJ02ReportsDataVoList.add(vo);
        }

        return TJ02ReportsDataVoList;
    }

    @Override
    public List<TJ02ReportsDataVo> virtualReportDataGeneration(TJ02ReportsDataReq req) {

        // 需要打印的报告项目
        String reportItems = req.getReportItems();
        List<String> reportItemList = Arrays.stream(reportItems.split(",")).collect(Collectors.toList());
        if(!reportItemList.contains(ReportConstant.BRACELET_SPO2) &&
                !reportItemList.contains(ReportConstant.BRACELET_TEMPERATURE) &&
                !reportItemList.contains(ReportConstant.BRACELET_HEART_RATE)) {
            System.err.println("不支持的报告类型：" + reportItems);
            throw new ServiceException("不支持的报告类型！");
        }

        // 查询患者信息
        Long visitNo = Long.valueOf(req.getVisitNos());
        PatientDetailInfoVo detailInfo = patVisitMapper.getDetailInfo(visitNo);

        // 获取预警值
        WarnSetVo warnValue = getWarnValue(visitNo);

        // 查询数据
        List<APISmartBraceletData> smartBraceletDataList = new ArrayList<>();
        smartBraceletDataList.addAll(remoteReportSmartBraceletDataList("ttt", DateUtils.parseDate("2025-05-03 10:13:24"), DateUtils.parseDate("2025-05-03 11:06:57")));
        smartBraceletDataList.addAll(remoteReportSmartBraceletDataList("zzz", DateUtils.parseDate("2025-05-03 11:07:21"), DateUtils.parseDate("2025-05-03 14:36:13")));
        smartBraceletDataList.addAll(remoteReportSmartBraceletDataList("yyy", DateUtils.parseDate("2025-05-03 14:36:21"), DateUtils.parseDate("2025-05-04 10:13:24")));

        // 生成报告
        TJ02ReportsDataVo vo = new TJ02ReportsDataVo();
        vo.setPatInfo(detailInfo);
        if(! smartBraceletDataList.isEmpty()) {
            // 按时间排序
            List<APISmartBraceletData> smartBraceletData = smartBraceletDataList.stream().sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime).reversed()).collect(Collectors.toList());
            for (String item : reportItemList) {
                getReportDataVo(smartBraceletData, item, vo, detailInfo.getVisitTime(), warnValue);
            }
        }

        // 返回数据
        List<TJ02ReportsDataVo> TJ02ReportsDataVoList = new ArrayList<>();
        TJ02ReportsDataVoList.add(vo);
        return TJ02ReportsDataVoList;
    }

    /**
     * 获取报告数据
     */
    private void getReportDataVo(List<APISmartBraceletData> smartBraceletData, String item, TJ02ReportsDataVo vo, Date visitTime, WarnSetVo warnSet) {
        if(vo == null) {
            vo = new TJ02ReportsDataVo();
        }
        if(ReportConstant.BRACELET_HEART_RATE.equals(item)) {
            // 心率
            TJ02Report report = getBraceletReport(smartBraceletData, ReportConstant.BRACELET_HEART_RATE);
            List<Integer> heartRateAxis = report.getValues();

            HeartRateReportVo heartRateReportVo = new HeartRateReportVo();
            heartRateReportVo.setReportTime(visitTime);
            heartRateReportVo.setAbscissa(report.getTimes());
            heartRateReportVo.setHeartRateAxis(heartRateAxis);
            heartRateReportVo.setHighestHeartRate(heartRateAxis.stream().mapToInt(Integer::intValue).max().orElse(0));
            heartRateReportVo.setLowestHeartRate(heartRateAxis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).min().orElse(0));
            heartRateReportVo.setAvgHeartRate((int) heartRateAxis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).average().orElse(0));
            heartRateReportVo.setLowWarnValue(warnSet.getHrLow());
            heartRateReportVo.setHighWarnValue(warnSet.getHrHigh());
            vo.setHeartRateReportVo(heartRateReportVo);
        }
        if(ReportConstant.BRACELET_SPO2.equals(item)) {
            // 血氧
            TJ02Report spo2Report = getBraceletReport(smartBraceletData, ReportConstant.BRACELET_SPO2);
            List<Integer> spO2Axis = spo2Report.getValues();

            SpO2ReportVo spO2ReportVo = new SpO2ReportVo();
            spO2ReportVo.setReportDate(visitTime);
            spO2ReportVo.setAbscissa(spo2Report.getTimes());
            spO2ReportVo.setSpO2Axis(spO2Axis);
            spO2ReportVo.setHighestSpO2(spO2Axis.stream().mapToInt(Integer::intValue).max().orElse(0));
            spO2ReportVo.setLowestSpO2(spO2Axis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).min().orElse(0));
            spO2ReportVo.setAvgSpO2((int) spO2Axis.stream().filter(e -> e != 0).mapToInt(Integer::intValue).average().orElse(0));
            spO2ReportVo.setWarnValue(warnSet.getSpo2());
            vo.setSpO2ReportVo(spO2ReportVo);
        }
        if(ReportConstant.BRACELET_TEMPERATURE.equals(item)) {
            // 体温
            TJ02Report report = getBraceletReport(smartBraceletData, ReportConstant.BRACELET_TEMPERATURE);
            List<Double> temperatureAxis = new ArrayList<>();
            List<Integer> values = report.getValues();
            values.forEach(e -> {
                temperatureAxis.add((double) e / 10);
            });
            TemperatureReportVo temperatureReportVo = new TemperatureReportVo();
            temperatureReportVo.setReportDate(visitTime);
            temperatureReportVo.setAbscissa(report.getTimes());
            temperatureReportVo.setTemperatureRateAxis(temperatureAxis);
            temperatureReportVo.setHighestTemperatureRate(temperatureAxis.stream().mapToDouble(Double::doubleValue).max().orElse(0));
            temperatureReportVo.setLowestTemperatureRate(temperatureAxis.stream().mapToDouble(Double::doubleValue).min().orElse(0));
            double avg = temperatureAxis.stream().mapToDouble(Double::doubleValue).average().orElse(0);
            DecimalFormat decimalFormat = new DecimalFormat("#.0");
            temperatureReportVo.setAvgTemperatureRate(Double.valueOf(decimalFormat.format(avg)));
            temperatureReportVo.setLowWarnValue(warnSet.getTempLow());
            temperatureReportVo.setHighWarnValue(warnSet.getTempHigh());
            vo.setTemperatureReportVo(temperatureReportVo);
        }

    }

    /**
     * 整点报告数据
     */
    private void getHourlyNursingData(List<APISmartBraceletData> smartBraceletData, List<String> reportItemList, Date visitTime, TJ02ReportsDataVo vo) {
        List<HourlyNursingDataVo> hourlyNursingData = new ArrayList<>();
        Date start = visitTime;
        // 获取第一个整点
        Date end = DateUtils.getNextHourTime(start);
        while (!smartBraceletData.isEmpty()) {
            // 筛选出对应时间段的数据
            Date finalStart = start, finalEnd = end;
            List<APISmartBraceletData> intervalData = smartBraceletData.stream()
                    .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                    .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < finalEnd.getTime())
                    .collect(Collectors.toList());

            start = finalEnd;
            end = DateUtils.getNextHourTime(start);
            if(intervalData.isEmpty()) {
                continue;
            }
            // 获取整点护理数据值
            HourlyNursingDataVo dataVo = getHourlyValue(intervalData, reportItemList, start);
            hourlyNursingData.add(dataVo);

            // 移除
            smartBraceletData.removeAll(intervalData);
        }

        vo.setHourlyNursingData(hourlyNursingData);
    }

    private HourlyNursingDataVo getHourlyValue(List<APISmartBraceletData> timeData, List<String> reportItemList, Date dateTime){

        List<Integer> heartModeData = new ArrayList<>();
        List<Integer> tempModeData = new ArrayList<>();
        List<Integer> spo2ModeData = new ArrayList<>();

        Date start = timeData.get(0).getAcquisitionTime();
        // 取每十分钟数据的数据
        for (int j = 0; j < 6; j ++) {
            // 加十分钟
            Date end = DateUtils.getNext10MinuteTime(start);

            // 获取十分钟的区间数据
            Date finalStart = start;
            List<APISmartBraceletData> intervalData = timeData.stream()
                    .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                    .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < end.getTime())
                    .collect(Collectors.toList());
            start = end;
            if (intervalData.isEmpty()) {
                continue;
            }

            // 计算整点数据值
            for(String type : reportItemList) {
                // 剔除掉脉率、血氧同时为初始值的数据
                List<APISmartBraceletData> excludeInitialValueDatas = intervalData.stream().filter(e -> e.getHeartRate() != EquipmentConstants.INITIAL_HEARTRATE_VALUE && e.getSpo2() != EquipmentConstants.INITIAL_SPO2_VALUE)
                        .collect(Collectors.toList());

                if(ReportConstant.BRACELET_HEART_RATE.equals(type)) {
                    // 脉率众数
                    List<Integer> heartData = excludeInitialValueDatas.stream()
                            .map(APISmartBraceletData::getHeartRate)
                            .filter(e -> e > 0)
                            .collect(Collectors.toList());
                    heartModeData.add(heartData.isEmpty() ? EquipmentConstants.INITIAL_HEARTRATE_VALUE : (heartData.size() == 1 ? heartData.get(0) : ReportUtil.getMode(heartData)));
                }

                if(ReportConstant.BRACELET_SPO2.equals(type)) {
                    // 血氧众数
                    List<Integer> spo2Data = intervalData.stream()
                            .map(APISmartBraceletData::getSpo2)
                            .filter(e -> e > 0)
                            .collect(Collectors.toList());
                    spo2ModeData.add(spo2Data.isEmpty() ? EquipmentConstants.INITIAL_SPO2_VALUE : (spo2Data.size() == 1 ? spo2Data.get(0) : ReportUtil.getMode(spo2Data)));
                }

                if(ReportConstant.BRACELET_TEMPERATURE.equals(type)) {
                    // 体温众数
                    List<Integer> tempData = intervalData.stream()
                            .map(APISmartBraceletData::getTemperature)
                            .filter(e -> e != null && e > 0 && EquipmentConstants.INITIAL_TEMPERATURE_VALUE != e && EquipmentConstants.INVALID_TEMPERATURE2 != e)
                            .collect(Collectors.toList());
                    if(! tempData.isEmpty()) {
                        tempModeData.add(tempData.size() == 1 ? tempData.get(0) : ReportUtil.getMode(tempData));
                    }
                }
            }
        }
        // 脉率平均数据
        double heartAvg = ReportUtil.getAvg(heartModeData);
        // 体温平均数据
        double tempAvg = ReportUtil.getAvg(tempModeData);
        // 血氧平均数据
        double spo2Avg = ReportUtil.getAvg(spo2ModeData);

        HourlyNursingDataVo dataVo = new HourlyNursingDataVo();
        dataVo.setDateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM, dateTime));
        dataVo.setHeartRate(heartAvg != 0 ? ReportUtil.doubleFmt(heartAvg, 0) : "-");
        dataVo.setSpO2(spo2Avg != 0 ? ReportUtil.doubleFmt(spo2Avg, 0) : "-");
        double value = tempAvg / 10;
        dataVo.setTemperature(tempAvg != 0 ? ReportUtil.doubleFmt(value, 1) : "-");
        return dataVo;
    }

    @Override
    public ScreenSignVo getPatBraceletSign(Long visitNo) {

        // 获取患者开单时间和出院时间
        PatVisitIntervalData intervalData = getTimes(visitNo);
        Date outTime = intervalData.getOutTime();

        List<APISmartBraceletData> smartBraceletDataList = listSmartBraceletData(visitNo, outTime);
        // 心率数据
        List<Date> heartRateAbscissa = new ArrayList<>();
        List<Integer> heartRateAxis = new ArrayList<>();
        // 血氧数据
        List<Date> spO2Abscissa = new ArrayList<>();
        List<Integer> spo2Axis = new ArrayList<>();
        // 体温数据
        List<Date> temperatureVoAbscissa = new ArrayList<>();
        List<Double> temperatureVoAxis = new ArrayList<>();

        smartBraceletDataList.forEach(e -> {
            Date acquisitionTime = e.getAcquisitionTime();
            Integer heartRate = e.getHeartRate();
            if (heartRate != null) {
                heartRateAbscissa.add(acquisitionTime);
                heartRateAxis.add(heartRate);
            }
            Integer spo2 = e.getSpo2();
            if (spo2 != null) {
                spO2Abscissa.add(acquisitionTime);
                spo2Axis.add(spo2);
            }
            Integer temperature = e.getTemperature();
            if (temperature != null && EquipmentConstants.INITIAL_TEMPERATURE_VALUE != temperature && EquipmentConstants.INVALID_TEMPERATURE2 != temperature && 0 != temperature
                    && (StringUtils.isEmpty(e.getPlugStatus()) || SensorConstants.SENSOR_STATUS_LEGAL.equals(e.getPlugStatus()))) {
                temperatureVoAbscissa.add(acquisitionTime);
                temperatureVoAxis.add((double) temperature / 10);
            }
        });

        HeartRateVo heartRateVo = new HeartRateVo();
        heartRateVo.setHeartRateAbscissa(heartRateAbscissa);
        heartRateVo.setHeartRateAxis(heartRateAxis);
        SpO2Vo spO2Vo = new SpO2Vo();
        spO2Vo.setSpO2Axis(spo2Axis);
        spO2Vo.setSpO2Abscissa(spO2Abscissa);
        TemperatureVo temperatureVo = new TemperatureVo();
        temperatureVo.setTemperatureVoAbscissa(temperatureVoAbscissa);
        temperatureVo.setTemperatureVoAxis(temperatureVoAxis);

        ScreenSignVo screenSignVo = new ScreenSignVo();
        screenSignVo.setHeartRateVo(heartRateVo);
        screenSignVo.setSpO2Vo(spO2Vo);
        screenSignVo.setTemperatureVo(temperatureVo);
        return screenSignVo;
    }

    /**
     * 每个小时整点数据
     * 三种方式：
     * 1、使用加权平均数：加权平均 = (数据1 * 权重1 + 数据2 * 权重2 + … + 数据n * 权重n) / (权重1 + 权重2 + … + 权重n)
     * 2、中位数
     * 3、众数
     * @param req
     * @return
     */
    @Override
    public TableDataInfo getHourlyData(HourlyDataReq req) {
        // 如果没日期，默认当天
        String nursingDay = req.getNursingDay();
        if(StringUtils.isBlank(nursingDay)) {
            nursingDay = DateUtils.getDate();
        }

        // 1、查询就诊中的患者
        String hospitalId = SecurityUtils.getLoginUser().getSysUser().getHospitalId();
        String deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        PageHelper.startPage(req.getPage(), 10);
        TPatVisit param = new TPatVisit();
        param.setHospitalId(hospitalId);
        param.setDeptId(deptId);
        param.setVisitStatus(req.getVisitStatus());
        List<TPatVisit> visitList = patVisitMapper.selectListToCalculateHourlyData(hospitalId, deptId, req.getVisitStatus(), nursingDay);
        PageInfo<TPatVisit> pageInfo = new PageInfo<>(visitList);
        List<TPatVisit> list = pageInfo.getList();

        // 返回表格数据
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(doSearchHourlyDatas(list, nursingDay));
        rspData.setMsg("查询成功");
        rspData.setTotal(pageInfo.getTotal());
        return rspData;
    }

    private List<Map<String, Object>> doSearchHourlyDatas(List<TPatVisit> list, String nursingDay){
        // 要调取的时间点，及属性名
        String jsonStr = "[" +
                "{\"min\":\"23:00:00\",\"max\":\"00:00:00\",\"spo2_attr\":\"spo2_00\",\"heart_attr\":\"heart_00\",\"temperature_attr\":\"temperature_00\"}," +
                "{\"min\":\"00:00:00\",\"max\":\"01:00:00\",\"spo2_attr\":\"spo2_01\",\"heart_attr\":\"heart_01\",\"temperature_attr\":\"temperature_01\"}," +
                "{\"min\":\"01:00:00\",\"max\":\"02:00:00\",\"spo2_attr\":\"spo2_02\",\"heart_attr\":\"heart_02\",\"temperature_attr\":\"temperature_02\"}," +
                "{\"min\":\"02:00:00\",\"max\":\"03:00:00\",\"spo2_attr\":\"spo2_03\",\"heart_attr\":\"heart_03\",\"temperature_attr\":\"temperature_03\"}," +
                "{\"min\":\"03:00:00\",\"max\":\"04:00:00\",\"spo2_attr\":\"spo2_04\",\"heart_attr\":\"heart_04\",\"temperature_attr\":\"temperature_04\"}," +
                "{\"min\":\"04:00:00\",\"max\":\"05:00:00\",\"spo2_attr\":\"spo2_05\",\"heart_attr\":\"heart_05\",\"temperature_attr\":\"temperature_05\"}," +
                "{\"min\":\"05:00:00\",\"max\":\"06:00:00\",\"spo2_attr\":\"spo2_06\",\"heart_attr\":\"heart_06\",\"temperature_attr\":\"temperature_06\"}," +
                "{\"min\":\"06:00:00\",\"max\":\"07:00:00\",\"spo2_attr\":\"spo2_07\",\"heart_attr\":\"heart_07\",\"temperature_attr\":\"temperature_07\"}," +
                "{\"min\":\"07:00:00\",\"max\":\"08:00:00\",\"spo2_attr\":\"spo2_08\",\"heart_attr\":\"heart_08\",\"temperature_attr\":\"temperature_08\"}," +
                "{\"min\":\"08:00:00\",\"max\":\"09:00:00\",\"spo2_attr\":\"spo2_09\",\"heart_attr\":\"heart_09\",\"temperature_attr\":\"temperature_09\"}," +
                "{\"min\":\"09:00:00\",\"max\":\"10:00:00\",\"spo2_attr\":\"spo2_10\",\"heart_attr\":\"heart_10\",\"temperature_attr\":\"temperature_10\"}," +
                "{\"min\":\"10:00:00\",\"max\":\"11:00:00\",\"spo2_attr\":\"spo2_11\",\"heart_attr\":\"heart_11\",\"temperature_attr\":\"temperature_11\"}," +
                "{\"min\":\"11:00:00\",\"max\":\"12:00:00\",\"spo2_attr\":\"spo2_12\",\"heart_attr\":\"heart_12\",\"temperature_attr\":\"temperature_12\"}," +
                "{\"min\":\"12:00:00\",\"max\":\"13:00:00\",\"spo2_attr\":\"spo2_13\",\"heart_attr\":\"heart_13\",\"temperature_attr\":\"temperature_13\"}," +
                "{\"min\":\"13:00:00\",\"max\":\"14:00:00\",\"spo2_attr\":\"spo2_14\",\"heart_attr\":\"heart_14\",\"temperature_attr\":\"temperature_14\"}," +
                "{\"min\":\"14:00:00\",\"max\":\"15:00:00\",\"spo2_attr\":\"spo2_15\",\"heart_attr\":\"heart_15\",\"temperature_attr\":\"temperature_15\"}," +
                "{\"min\":\"15:00:00\",\"max\":\"16:00:00\",\"spo2_attr\":\"spo2_16\",\"heart_attr\":\"heart_16\",\"temperature_attr\":\"temperature_16\"}," +
                "{\"min\":\"16:00:00\",\"max\":\"17:00:00\",\"spo2_attr\":\"spo2_17\",\"heart_attr\":\"heart_17\",\"temperature_attr\":\"temperature_17\"}," +
                "{\"min\":\"17:00:00\",\"max\":\"18:00:00\",\"spo2_attr\":\"spo2_18\",\"heart_attr\":\"heart_18\",\"temperature_attr\":\"temperature_18\"}," +
                "{\"min\":\"18:00:00\",\"max\":\"19:00:00\",\"spo2_attr\":\"spo2_19\",\"heart_attr\":\"heart_19\",\"temperature_attr\":\"temperature_19\"}," +
                "{\"min\":\"19:00:00\",\"max\":\"20:00:00\",\"spo2_attr\":\"spo2_20\",\"heart_attr\":\"heart_20\",\"temperature_attr\":\"temperature_20\"}," +
                "{\"min\":\"20:00:00\",\"max\":\"21:00:00\",\"spo2_attr\":\"spo2_21\",\"heart_attr\":\"heart_21\",\"temperature_attr\":\"temperature_21\"}," +
                "{\"min\":\"21:00:00\",\"max\":\"22:00:00\",\"spo2_attr\":\"spo2_22\",\"heart_attr\":\"heart_22\",\"temperature_attr\":\"temperature_22\"}," +
                "{\"min\":\"22:00:00\",\"max\":\"23:00:00\",\"spo2_attr\":\"spo2_23\",\"heart_attr\":\"heart_23\",\"temperature_attr\":\"temperature_23\"}," +
                "]";
        JSONArray timeArr = JSON.parseArray(jsonStr);

        List<Map<String, Object>> datas = new ArrayList<>();
        // 2、遍历患者信息，查询开单使用的设备
        for (TPatVisit visitVo : list) {
            // 患者就诊号
            String visitNoStr = String.valueOf(visitVo.getVisitNo());
            // 先查询缓存
            String cacheKey = CacheConstants.HOURLY_DATA + visitNoStr + ":" + nursingDay;
            Map<String, Object> cacheMap = redisService.getCacheMap(cacheKey);
            if (cacheMap != null && !cacheMap.isEmpty()) {
                datas.add(cacheMap);
                continue ;
            }

            PatVisitIntervalData intervalTime = DateUtils.getIntervalTime(visitVo.getVisitTime(), visitVo.getRentalDays(), visitVo.getOutTime(), visitVo.getDataType());
            // 出院时间
            Date outTime = intervalTime.getOutTime();

            // 患者信息
            Map<String, Object> info = new HashMap<>();
            info.put("name", visitVo.getPatientName());
            info.put("age", visitVo.getAge());
            info.put("bedNo", visitVo.getBedNo());
            info.put("diagnosis", visitVo.getDiagnosis());

            // 2.3、查询患者就诊期间采集的数据
            List<APISmartBraceletData> dataList = listSmartBraceletData(visitVo.getVisitNo(), outTime);
            if(dataList.isEmpty()) {
                datas.add(info);
                setCache(cacheKey, info);
                continue;
            }

            // 3、循环查询各时间点，并查询各个时间点的数据
            for (int i = 0; i < timeArr.size(); i ++) {
                JSONObject jsonObject = timeArr.getJSONObject(i);
                String min = jsonObject.getString("min");
                String max = jsonObject.getString("max");

                Date minTime = DateUtils.parseDate(nursingDay + " " + min);
                Date maxTime = DateUtils.parseDate(nursingDay + " " + max);
                if("00:00:00".equals(max)) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(minTime);
                    // 将日期减去一天
                    calendar.add(Calendar.DATE, -1);
                    // 获取减去一天后的日期
                    minTime = calendar.getTime();
                }
                Date finalMinTime = minTime;
                // 3.1、筛选出对应时间段的数据
                List<APISmartBraceletData> timeData = dataList.stream()
                        .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                        .filter(e -> e.getAcquisitionTime().getTime() >= finalMinTime.getTime() && e.getAcquisitionTime().getTime() < maxTime.getTime())
                        .collect(Collectors.toList());
                if (timeData.isEmpty()) {
                    continue;
                }

                List<Integer> heartModeData = new ArrayList<>();
                List<Integer> tempModeData = new ArrayList<>();
                List<Integer> spo2ModeData = new ArrayList<>();
                Date start = minTime;
                // 3.2、取每十分钟数据的数据
                for (int j = 0; j < 6; j ++) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(start);
                    // 加十分钟
                    calendar.add(Calendar.MINUTE, 10);
                    Date end = calendar.getTime();

                    // 获取十分钟的区间数据
                    Date finalStart = start;
                    List<APISmartBraceletData> intervalData = timeData.stream()
                            .sorted(Comparator.comparing(APISmartBraceletData::getAcquisitionTime))
                            .filter(e -> e.getAcquisitionTime().getTime() >= finalStart.getTime() && e.getAcquisitionTime().getTime() < end.getTime())
                            .collect(Collectors.toList());
                    start = end;
                    if (intervalData.isEmpty()) {
                        continue;
                    }

                    // 剔除掉脉率、血氧同时为初始值的数据
                    List<APISmartBraceletData> excludeInitialValueDatas = intervalData.stream().filter(e -> e.getHeartRate() != EquipmentConstants.INITIAL_HEARTRATE_VALUE && e.getSpo2() != EquipmentConstants.INITIAL_SPO2_VALUE)
                            .collect(Collectors.toList());

                    // 脉率众数
                    List<Integer> heartData = excludeInitialValueDatas.stream()
                            .map(APISmartBraceletData::getHeartRate)
                            .filter(e -> e > 0)
                            .collect(Collectors.toList());
                    heartModeData.add(heartData.isEmpty() ? EquipmentConstants.INITIAL_HEARTRATE_VALUE : (heartData.size() == 1 ? heartData.get(0) : ReportUtil.getMode(heartData)));

                    // 血氧众数
                    List<Integer> spo2Data = intervalData.stream()
                            .map(APISmartBraceletData::getSpo2)
                            .filter(e -> e > 0)
                            .collect(Collectors.toList());
                    spo2ModeData.add(spo2Data.isEmpty() ? EquipmentConstants.INITIAL_SPO2_VALUE : (spo2Data.size() == 1 ? spo2Data.get(0) : ReportUtil.getMode(spo2Data)));

                    // 体温众数
                    List<Integer> tempData = intervalData.stream()
                            .map(APISmartBraceletData::getTemperature)
                            .filter(e -> e != null && e > 0 && EquipmentConstants.INITIAL_TEMPERATURE_VALUE != e && EquipmentConstants.INVALID_TEMPERATURE2 != e)
                            .collect(Collectors.toList());
                    if(!tempData.isEmpty()) {
                        tempModeData.add(tempData.size() == 1 ? tempData.get(0) : ReportUtil.getMode(tempData));
                    }
                }
                // 脉率平均数据
                double heartAvg = ReportUtil.getAvg(heartModeData);
                // 体温平均数据
                double tempAvg = ReportUtil.getAvg(tempModeData);
                // 血氧平均数据
                double spo2Avg = ReportUtil.getAvg(spo2ModeData);

                // 3.2、封装数据
                info.put(jsonObject.getString("spo2_attr"), spo2Avg != 0 ? ReportUtil.doubleFmt(spo2Avg, 0) : "-");
                info.put(jsonObject.getString("heart_attr"), heartAvg != 0 ? ReportUtil.doubleFmt(heartAvg, 0) : "-");
                double value = tempAvg / 10;
                info.put(jsonObject.getString("temperature_attr"), tempAvg != 0 ? ReportUtil.doubleFmt(value, 1) : "-");
            }

            // 判断是否已结束
            boolean isEnd = PatVisitStatusConstants.VISIT_STATUS_END.equals(visitVo.getVisitStatus());
            if(isEnd) {
                setCache(cacheKey, info);
            }

            datas.add(info);
        }

        return datas;
    }

    /**
     * 设置缓存
     * @param cacheKey 缓存键
     * @param info 缓存内容
     */
    private void setCache(String cacheKey, Map<String, Object> info){
        // 保存缓存数据
        redisService.setCacheMap(cacheKey, info);
        // 缓存过期时间（取随机数）
        // 为了不让缓存同一时间全部失效，初始1小时（3600秒）加上随机的秒数
        long expireSeconds = 3600L + (new Random().nextInt(1000));
        redisService.expire(cacheKey, expireSeconds);
    }

    @Override
    public AjaxResult getBraceletHistoryData(EquipmentHistoryReq req) {
        Long visitNo = req.getVisitNo();

        // 1、查询患者就诊信息
        TPatVisit patVisit = patVisitMapper.selectTPatVisitByVisitNo(visitNo);
        if(patVisit == null) {
            AjaxResult.error("患者就诊信息不存在！");
        }
        // 获取患者预计出院时间
        PatVisitIntervalData intervalTime = DateUtils.getIntervalTime(patVisit.getVisitTime(), patVisit.getRentalDays(), null, patVisit.getDataType());

        // 2、查询患者使用的设备
        List<TEquipmentUsageRecords> tEquipmentUsageRecords = equipmentUsageRecordsMapper.selectAllUseRecordByVisitNo(visitNo);
        List<BraceletHistoryDataReqEquipmentInfo> equipmentInfos = new ArrayList<>();
        for (TEquipmentUsageRecords record : tEquipmentUsageRecords) {
            if(EquipmentConstants.EQUIPMENT_TYPE_SMART_BRACELET_TYPE.equals(record.getEquipmentType())) {
                BraceletHistoryDataReqEquipmentInfo info = new BraceletHistoryDataReqEquipmentInfo();
                info.setEquipmentNo(record.getEquipmentNo());
                info.setStartTime(record.getStartTime());
                info.setEndTime(record.getEndTime() == null || record.getEndTime().after(intervalTime.getOutTime()) ? intervalTime.getOutTime() : record.getEndTime());

                equipmentInfos.add(info);
            }
        }

        // 3、组装参数，请求数据
        BraceletHistoryDataReq braceletHistoryDataReq = new BraceletHistoryDataReq();
        braceletHistoryDataReq.setEquipmentInfos(equipmentInfos);
        braceletHistoryDataReq.setPageNum(req.getPageNum());
        braceletHistoryDataReq.setPageSize(req.getPageSize());
        R<Object> result = remoteTJ02DataService.reqBraceletHistoryData(braceletHistoryDataReq, SecurityConstants.INNER);
        if(StringUtils.isNull(result) || R.FAIL == result.getCode()){
            throw new ServiceException("获取设备历史数据失败！");
        }
        return AjaxResult.success(result.getData());
    }

    /**
     * 获取预警值
     */
    private WarnSetVo getWarnValue(Long visitNo){

        // 当前医院ID和科室ID
        String hospitalId = "";
        String deptId = "";
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(loginUser != null && loginUser.getSysUser() != null) {
            hospitalId = loginUser.getSysUser().getHospitalId();
            deptId = loginUser.getSysUser().getDeptId();
        } else {
            // 通过查询患者信息获取医院ID和科室ID
            TPatVisit visit = patVisitMapper.selectTPatVisitByVisitNo(visitNo);
             if(visit != null) {
                 hospitalId = visit.getHospitalId();
                 deptId = visit.getDeptId();
             }
        }
        WarnSetVo setVo = new WarnSetVo();
        // 查询科室的预警值设置
        List<TWarnSettingHospital> tWarnSettingHospitals = tWarnSettingHospitalMapper.selectHospitalWarnSet(hospitalId, deptId);
        if(tWarnSettingHospitals != null && ! tWarnSettingHospitals.isEmpty()) {
            for (TWarnSettingHospital set : tWarnSettingHospitals) {
                if(WarnConstants.WARN_TYPE_BRACELET_SPO2.equals(set.getWarnType())) {
                    setVo.setSpo2(set.getLowerLimit().longValue());
                }
                if(WarnConstants.WARN_TYPE_BPM.equals(set.getWarnType())) {
                    setVo.setHrLow(set.getLowerLimit().longValue());
                    setVo.setHrHigh(set.getUpperLimit().longValue());
                }
                if(WarnConstants.WARN_TYPE_TEMPERATURE.equals(set.getWarnType())) {
                    setVo.setTempLow(set.getLowerLimit());
                    setVo.setTempHigh(set.getUpperLimit());
                }
            }
        }
        // 如果配置为空，则使用公共预警值
        if(setVo.getSpo2() == null
                || setVo.getHrLow() == null || setVo.getHrHigh() == null
                || setVo.getTempLow() == null || setVo.getTempHigh() == null) {
            List<TWarnSettingHospital> defaultSet = tWarnSettingHospitalMapper.selectPublicWarnSet();
            // 血氧
            if(setVo.getSpo2() == null) {
                List<TWarnSettingHospital> spo2Sets = defaultSet
                        .stream()
                        .filter(tWarnSettingHospital -> WarnConstants.WARN_TYPE_BRACELET_SPO2.equals(tWarnSettingHospital.getWarnType()))
                        .collect(Collectors.toList());
                TWarnSettingHospital spo2Set = spo2Sets.get(0);
                setVo.setSpo2(spo2Set.getLowerLimit().longValue());
            }

            // 脉率
            if(setVo.getHrLow() == null || setVo.getHrHigh() == null) {
                List<TWarnSettingHospital> hrSets = defaultSet
                        .stream()
                        .filter(tWarnSettingHospital -> WarnConstants.WARN_TYPE_BPM.equals(tWarnSettingHospital.getWarnType()))
                        .collect(Collectors.toList());
                TWarnSettingHospital hrSet = hrSets.get(0);

                if(setVo.getHrLow() == null) {
                    setVo.setHrLow(hrSet.getLowerLimit().longValue());
                }
                if(setVo.getHrHigh() == null) {
                    setVo.setHrHigh(hrSet.getUpperLimit().longValue());
                }
            }

            // 体温
            if(setVo.getTempLow() == null || setVo.getTempHigh() == null) {
                List<TWarnSettingHospital> tempSets = defaultSet
                        .stream()
                        .filter(tWarnSettingHospital -> WarnConstants.WARN_TYPE_TEMPERATURE.equals(tWarnSettingHospital.getWarnType()))
                        .collect(Collectors.toList());
                TWarnSettingHospital tempSet = tempSets.get(0);
                if(setVo.getTempLow() == null) {
                    setVo.setTempLow(tempSet.getLowerLimit());
                }
                if(setVo.getTempHigh() == null) {
                    setVo.setTempHigh(tempSet.getUpperLimit());
                }
            }
        }

        return setVo;
    }
}
